using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Core;
using Essensoft.Paylink.Alipay;
using Essensoft.Paylink.Alipay.Request;
using Essensoft.Paylink.Alipay.Response;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

namespace Admin.NET.Application;

/// <summary>
/// 支付宝支付
/// </summary>
[ApiDescriptionSettings(new string[] { "业务应用" }, Order = 100)]
public class AliPayService : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly UserManager _userManager;

	private readonly SqlSugarRepository<AliPayProvider> _rep;

	private readonly IAlipayClient _client;

	public AliPayService(UserManager userManager, SqlSugarRepository<AliPayProvider> rep, IAlipayClient client)
	{
		_userManager = userManager;
		_rep = rep;
		_client = client;
	}

	[HttpGet("/alipay/getbuyerid")]
	public async Task<dynamic> GetBuyerId(string authCode)
	{
		AliPayProvider baseOptions = await GetProvider();
		AliPaySub subOptions = await GetSubOptions();
		AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest
		{
			Code = authCode,
			GrantType = "authorization_code"
		};
		AlipayOptions options = new AlipayOptions
		{
			AlipayPublicKey = baseOptions.AlipayPublicKey,
			AppId = baseOptions.AppId,
			AppPrivateKey = baseOptions.AppPrivateKey,
			EncryptKey = baseOptions.EncryptKey
		};
		AlipaySystemOauthTokenResponse response = await _client.ExecuteAsync(request, options, null, subOptions.AppAuthToken);
		if (response.IsError)
		{
			throw Oops.Bah(response.Msg);
		}
		return response.UserId;
	}

	/// <summary>
	/// 创建订单编号
	/// </summary>
	/// <returns></returns>
	private string CreateOrderNo()
	{
		Random r = new Random();
		int r1 = r.Next(1, 9) * 10;
		int r2 = r.Next(1, 9) * 10;
		DateTime tmpTime = DateTime.Now;
		string now = tmpTime.ToString("yyMMddHHmmss") + "99" + tmpTime.Millisecond;
		return now + Convert.ToString(r1) + Convert.ToString(r2);
	}

	private async Task<AliPayProvider> GetProvider()
	{
		AliPayProvider data = await _rep.AsQueryable().FirstAsync();
		if (data == null)
		{
			throw Oops.Bah("该平台暂未开通支付宝支付，请线下缴费");
		}
		return data;
	}

	private async Task<AliPaySub> GetSubOptions()
	{
		AliPaySub data = await (from u in _rep.Context.Queryable<AliPaySub>()
			where u.SubTenantId == _userManager.TenantId
			select u).FirstAsync();
		if (data == null)
		{
			throw Oops.Bah("暂未开通支付宝支付，请线下缴费");
		}
		return data;
	}

	[HttpPost("/ali/pay/createorder")]
	public async Task<dynamic> CreateOrder([FromBody] CreateAliOrderInput input)
	{
		AliPayProvider baseOptions = await GetProvider();
		AliPaySub subOptions = await GetSubOptions();
		string orderNo = CreateOrderNo();
		Room room = await (from w in _rep.Context.Queryable<Room>()
			where w.Id == input.RoomId
			select w).FirstAsync();
		if (room == null)
		{
			throw Oops.Bah("该房间不存在，无法充值缴费");
		}
		AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
		request.SetNotifyUrl(baseOptions.AliPayPayUrl);
		string Contentjson = JsonConvert.SerializeObject(new Dictionary<string, object>
		{
			{ "out_trade_no", orderNo },
			{ "total_amount", input.Total },
			{ "subject", input.Description },
			{ "buyer_id", input.BuyerId },
			{ "timeout_express", "15m" },
			{ "product_code", "JSAPI_PAY" },
			{ "op_app_id", subOptions.SubAppId },
			{ "seller_id", subOptions.PID }
		});
		request.BizContent = Contentjson;
		AlipayOptions options = new AlipayOptions
		{
			AlipayPublicKey = baseOptions.AlipayPublicKey,
			AppId = baseOptions.AppId,
			AppPrivateKey = baseOptions.AppPrivateKey,
			EncryptKey = baseOptions.EncryptKey
		};
		AlipayTradeCreateResponse response = await _client.ExecuteAsync(request, options, null, subOptions.AppAuthToken);
		if (response.IsError)
		{
			throw Oops.Oh(response.SubMsg);
		}
		PaymentRecord wechatPay = new PaymentRecord
		{
			AppId = baseOptions.AppId,
			SubAppId = subOptions.SubAppId,
			OutTradeNo = orderNo,
			Remark = input.Description,
			Amount = decimal.Parse(input.Total),
			Rate = input.Rate,
			OpenId = input.BuyerId,
			Body = input.Description,
			IsPay = 0,
			PaymentName = "房间缴费",
			Subject = "房间缴费",
			PayType = PayTypeEnum.支付宝,
			BeforeAmount = room.Balance,
			BuildingId = room.BuildingId,
			OwnerId = room.OwnerId,
			RoomId = room.Id,
			CreateTime = DateTime.Now,
			CreateUserName = _userManager.RealName
		};
		if (input.IsCustomBill.GetValueOrDefault() == 1)
		{
			if (input.Bills == null || input.Bills.Count == 0)
			{
				throw Oops.Bah("无效账单，请重新进入页面");
			}
			List<long> billtypes = input.Bills.Select((CustomBill s) => s.BillType).ToList();
			List<BillType> types = await (from w in _rep.Context.Queryable<BillType>()
				where billtypes.Contains(w.Id)
				select w).ToListAsync();
			wechatPay.IsCustomBill = input.IsCustomBill;
			wechatPay.Bills = input.Bills.Select(delegate(CustomBill s)
			{
				BillType billType = types.Where((BillType w) => w.Id == s.BillType).FirstOrDefault();
				return new CustomBillRecord
				{
					BillType = s.BillType,
					Fee = s.Fee,
					Name = billType?.Name,
					IsSupportedInvoicing = billType?.IsSupportedInvoicing
				};
			}).ToList();
			wechatPay.CustomRoomBillId = input.CustomRoomBillId;
			wechatPay.PaymentName = input.PaymentName;
			wechatPay.Subject = input.PaymentName;
		}
		_rep.Context.Insertable(wechatPay).ExecuteCommand();
		return new
		{
			tradeNo = response.TradeNo,
			outTradeNumber = orderNo,
			Payee = subOptions.SubName,
			PayTime = wechatPay.CreateTime
		};
	}
}
